/*
修改一部分wbfs的数据(MAIN.DOL)使其变成补丁


1,读取NAND程序到目标内存作为程序
2,读取NAND汉化文件到目标内存
3,修改一些函数已适应修改汉化文本


    找到一个不经常用的函数，保证在显示之前不调用
        start或者最长的那个函数
        处理最长的那个函数时，需要判断是否已经初始化，如果已经初始化，则读取数据覆盖这个函数
    *注:已经不需要最长的函数，直接hook某函数，然后保证执行extend函数在把那个函数还原

    被hook的函数，应该跳转到hook，让hook加载extend文件，然后还原hook函数，再修改其他被hook的函数的数据

加载顺序
    extend.bin
    restore.bin
    hook.func

有些bug
    如修改了目标函数，会导致执行代码失败
        原因是有的指令缓存,需要设置 HID0.ICE  寄存器  (HID0|=(1<<15))

    t = lookup_table[(addr >> 5) & 0xfffff]
        如果t为0xff，需要重新加载指令缓存
        const u32 ICACHE_SETS = 128;
        const u32 ICACHE_WAYS = 8;
        const u32 ICACHE_BLOCK_SIZE = 8;
        指令缓存为 u32 data[ICACHE_SETS][ICACHE_WAYS][ICACHE_BLOCK_SIZE];
        set = (addr >> 5) & 0x7f;
        返回 data[set][t][(addr>>2) & 7]

        HID0.ICFI
            为刷新icache，当用户模式不能访问
            MSR.PR 为1表示用户模式

*/

#include "hook.h"

#if 0
void hook_func(){
nasm(".section	\".text\"");
nasm(".align 2");
nasm(".globl HOOK_80210C88");
nasm(".type	HOOK_80210C88, @function");
nasm("HOOK_80210C88:");
/*
一般情况下，需要保存r3-r13
*/
}
#else

//需要asm处理其他寄存器变量
extern void hook_asm();
void __hook_asm(){
nasm(".section	\".hook\"");
nasm(".align 2");
nasm(".globl hook_asm");
nasm(".type	hook_asm, @function");
nasm("hook_asm:");
#if 0
nasm("mr 9,1");     //sp参数
nasm("mflr 10");    //lr参数
#if 0
nasm("b hook");
#else
//hook函数会保存一些寄存器，如果直接调用,lr设置为跳到目标函数，这样就完美了
//返回一个SAVE数据，然后调用指针
nasm("bl hook");
nasm("mtlr 3");
nasm("blr");
#endif
#else
//应该保存所有寄存器
nasm("mr 0,3");
nasm("lis 3,0x80ff");
nasm("stw 1,4*1   (3)");
nasm("stw 2,4*2   (3)");
nasm("stw 0,4*3   (3)");
nasm("stw 4,4*4   (3)");
nasm("stw 5,4*5   (3)");
nasm("stw 6,4*6   (3)");
nasm("stw 7,4*7   (3)");
nasm("stw 8,4*8   (3)");
nasm("stw 9,4*9   (3)");
nasm("stw 10,4*10 (3)");
nasm("stw 11,4*11 (3)");
nasm("stw 12,4*12 (3)");
nasm("stw 13,4*13 (3)");
nasm("stw 14,4*14 (3)");
nasm("stw 15,4*15 (3)");
nasm("stw 16,4*16 (3)");
nasm("stw 17,4*17 (3)");
nasm("stw 18,4*18 (3)");
nasm("stw 19,4*19 (3)");
nasm("stw 20,4*20 (3)");
nasm("stw 21,4*21 (3)");
nasm("stw 22,4*22 (3)");
nasm("stw 23,4*23 (3)");
nasm("stw 24,4*24 (3)");
nasm("stw 25,4*25 (3)");
nasm("stw 26,4*26 (3)");
nasm("stw 27,4*27 (3)");
nasm("stw 28,4*28 (3)");
nasm("stw 29,4*29 (3)");
nasm("stw 30,4*30 (3)");
nasm("stw 31,4*31 (3)");
nasm("mflr 4");
nasm("mfcr 5");
nasm("mfctr 6");
nasm("stw 4,4*32 (3)");
nasm("stw 5,4*33 (3)");
nasm("stw 6,4*34 (3)");
nasm("mr 3,0");
nasm("bl hook");
/*
执行hook后，调用
*/
// nasm("mtlr 3");
// nasm("blr");
#endif
nasm(".section	\".text\"");
}

//直接hook
#if 0
int sub_80210C88(u32 r3,u32 r4,u32 r5,u32 r6){
#else
int hook(u32 r3,u32 r4,u32 r5,u32 r6,u32 r7,u32 r8,u32 r9,u32 r10){
#endif
    int (*extend_exec)() = (void*)EXTEND_ADDR;
    #if 0
    SAVE->r3 = r3;
    SAVE->r4 = r4;
    SAVE->r5 = r5;
    SAVE->r6 = r6;
    SAVE->sp = r9;
    SAVE->lr = r10;
    #endif

    int extend = IOS_Open(EXTEND_EXE,IPC_OPEN_READ);
    SAVE->hook_func = (u32)&hook_asm;
    SAVE->extend_fd = extend;
    if(extend>0){
        //打开成功,获得数据
        int read_size = 512;
        int offset = 0;
        u8 *data_ptr = (u8*)extend_exec;

        while(1){
            int ret = IOS_Read(extend,data_ptr,read_size);
            if(ret<read_size){
                //读取结束
                break;
            }
            data_ptr += ret;
        }
    }
    return extend_exec();
}
#endif